#pragma once
#include <iostream>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <cerrno>

using namespace std;

class EpollUtil
{
public:
    static int gsize;
    
    // 创建 epoll 模型, 返回 epoll 模型的文件描述符
    static int create()
    {
        int epfd = epoll_create(gsize);
        if (epfd < 0) 
        {
            cout << "Error: epoll 模型创建失败" << endl;
        }
        return epfd;
    }

    // 在 epfd 的 epoll 模型中添加 sock 文件描述符的 event 事件
    static bool addEvent(int epfd, int fd, uint32_t newEvent)
    {
        struct epoll_event toadd;
        toadd.data.fd = fd;                                                     // 填充文件描述符
        toadd.events = newEvent;                                               // 增加事件

        int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &toadd);
        cout << "成功添加了一个新连接 [fd = " << fd << "]" << endl;
        return ret == 0;
    }

    // 获取就绪事件
    static int getReadyEvents(int epfd, struct epoll_event* readyEvents, int readySize)
    {
        cout << "阻塞等待事件发生" << endl;
        int ret = epoll_wait(epfd, readyEvents, readySize, -1);                 // 获取就绪事件, -1 表示无期限阻塞式等待
        if (ret == -1) {                                                        // 0 表示超时, -1 报错            
            cerr << "Error: 获取就绪事件失败" << endl;
        }
        cout << "成功获取就绪事件" << endl;
        return ret;
    }

    // 在 epfd 模型中修改对某些事件的关心与否
    static void modifyEvent(int epfd, int fd, uint32_t event)
    {
        struct epoll_event tochange;
        tochange.data.fd = fd;
        tochange.events = event;
        epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &tochange);
    }

    // 移除对特定事件的关心
    static int deleteEvent(int epfd, int sock)
    {
        // 移除所有事件
        int n = epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr); 
        return n == 0;
    }
};

 int EpollUtil::gsize = 256;